import React from 'react';
import moment from 'moment';
import { deepFullCopy, messages, queryCurrencyPrecision, addCalculate, mulCalculate } from "share/common";
import { Modal } from 'antd';

//保存费用前字段检查
function validateFieldsValue(params, options) {
  return new Promise((resolve, reject) => {
    const {
      target, values, expenseType, nowExpense, nowCurrency, businessCardConsumptions, receiptList, expenseApportion,
      expenseReport, actualApportionAmount, unitPriceMode, attachments, invoiceCurrencyCode, expenseAmortise
    } = params;
    const {
      invoiceConfigOpt: { bizCardCheck, enableZero, amountReceiptCheck, pcfpAmountCheck },
    } = options;
    const expenseAmount = values.hasOwnProperty('amount') && typeof values.amount === 'number'
      ? +values.amount : +nowExpense.amount;
    let errorMessages = [];
    if (!expenseType.id) {
      errorMessages.push(messages('expense-1.key213')/*请选择费用类型*/);
    }
    if (businessCardConsumptions.length > 0) {
      let getWriteOffAmt = info => {
        let relateInvoice = info.bankTrxInvoiceRelations && info.bankTrxInvoiceRelations
          .filter(item => item.invoiceOID === nowExpense.invoiceOID)[0];
        return relateInvoice && relateInvoice.invoiceOID === nowExpense.invoiceOID ? +relateInvoice.writeOffAmt || 0 : 0
      };
      let businessCardTotalAmount = businessCardConsumptions
        .reduce((pre, now) => now.balanceAmount + getWriteOffAmt(now) + pre, 0)
        .toFixed(queryCurrencyPrecision(invoiceCurrencyCode));
      // 需要校验金额 存在非支付宝消费 则校验
      let needValidBusinessAmount = businessCardConsumptions.some(card => card.cardTypeCode !== 'ALIPAY');
      //商务卡配置以前是true或者false，现在改成1，2，3且做老数据兼容。
      // 1 不校验, 2 等于, 3 小于等于
      if (bizCardCheck !== 1) {
        if (businessCardConsumptions.some(item => item.posCurCod !== nowCurrency.currencyCode)) {
          errorMessages.push(messages('expense-1.key214')/*费用币种必须与消费账单入账币种一致*/);
        } else {
          if (bizCardCheck === 2 && Math.abs(expenseAmount - businessCardTotalAmount) > Number.EPSILON && needValidBusinessAmount) {
            errorMessages.push(messages('expense-1.key215')/*费用金额必须等于消费账单可报金额*/);
          }
          if ((bizCardCheck === 3 || !bizCardCheck) && (expenseAmount - businessCardTotalAmount) > Number.EPSILON && needValidBusinessAmount) {
            errorMessages.push(messages('expense-1.key216')/*费用金额必须小于等于消费账单可报金额*/);
          }
        }
      }
    }
    if (!enableZero && values.hasOwnProperty('amount') && !values.amount) {
      errorMessages.push(messages('expense-1.key217')/*金额不能为0*/);
    }

    //第三方费用修改金额
    if (
      expenseType.readonly &&
      expenseType.messageKey !== 'private.car.for.public' &&
      values.amount > nowExpense.orderAmount &&
      (expenseType.isAmountEditable && !expenseType.isAmountIncreased)
    ) {
      errorMessages.push(messages('expense-1.key218')/*金额不能大于原始金额*/);
    }
    if (receiptList.length < 1 && expenseType.invoiceRequired && expenseType.pasteInvoiceNeeded) {
      errorMessages.push(messages('expense-1.key219')/*请添加发票*/);
    }
    if (receiptList && receiptList.length > 0) {
      let priceTaxAmount = 0;
      let receiptCurrencyIsSameWithExpense = true;
      receiptList.map(item => {
        item.fee = item.fee || 0;
        priceTaxAmount = addCalculate(
          priceTaxAmount,
          item.fee / 100 + (item.nonDeductibleAmount ? item.nonDeductibleAmount / 100 : 0)
        );// 金额 = 价税合计 + 不可抵扣
        item.vatInvoiceCurrencyCode !== nowCurrency.currencyCode && (receiptCurrencyIsSameWithExpense = false);
      });
      if (
        (amountReceiptCheck === 0 || !amountReceiptCheck) &&
        expenseAmount > priceTaxAmount && receiptCurrencyIsSameWithExpense
      ) {
        errorMessages.push(messages('expense-1.key220')/*费用金额必须小于等于关联发票的总金额*/);
      } else if (
        (amountReceiptCheck === 2 || amountReceiptCheck === true) &&
        expenseAmount !== priceTaxAmount && receiptCurrencyIsSameWithExpense
      ) {
        errorMessages.push(messages('expense-1.key221')/*费用金额必须等于关联发票的总金额*/);
      }
      //若发票币种和费用原币种不一致
      if (amountReceiptCheck !== 1 && !receiptCurrencyIsSameWithExpense) {
        //费用和商务卡关联
        if (businessCardConsumptions.length > 0) {
          let receiptCurrencyIsSameWithBusiness = true;
          let businessOriAmt = 0;
          businessCardConsumptions.map(item => {
            businessOriAmt = addCalculate(businessOriAmt, item.oriCurAmt);
            if (receiptList.some(receipt => receipt.vatInvoiceCurrencyCode !== item.oriCurCod)) {
              receiptCurrencyIsSameWithBusiness = false;
            }
          });
          let needValidBusinessAmount = businessCardConsumptions.some(card => card.cardTypeCode !== 'ALIPAY');
          //校验当前费用下相关所有商务卡的交易币种必须和当前费用下相关所有发票币种一致
          if (!receiptCurrencyIsSameWithBusiness) {
            errorMessages.push(messages('expense-1.key222')/*发票币种必须和消费账单交易币种一致*/);
          } else {
            if ((amountReceiptCheck === 0 || !amountReceiptCheck) && businessOriAmt > priceTaxAmount && needValidBusinessAmount) {
              errorMessages.push(messages('expense-1.key223')/*消费账单交易金额必须小于等于发票的价税合计*/);
            }
            if ((amountReceiptCheck === 2 || amountReceiptCheck === true) && businessOriAmt !== priceTaxAmount && needValidBusinessAmount) {
              errorMessages.push(messages('expense-1.key224')/*消费账单交易金额必须等于发票的价税合计*/);
            }
          }
        } else {
          errorMessages.push(messages('expense-1.key225')/*发票币种必须与费用币种相同*/);
        }
      }
    }
    /**
     * @desc 增加条件判断 编辑中的费用分摊行都释放。1：是否有分摊行权限，|| 2：分摊数据中是否有关联的申请单分摊行OID （待优化）
     */
    let isRelatedApplication = () => {
      return expenseApportion && expenseApportion.some(item => !!item.applicationApportionmentId);
    };
    if (
      (isRelatedApplication() || expenseType.erApportionEnabled) &&
      expenseReport &&
      expenseApportion &&
      values.amount
    ) {
      if (expenseApportion.length === 0) {
        errorMessages.push(messages('expense-1.key226')/*分摊行数为0，不可保存费用*/)
      } else {
        let targetApportion = [];
        let expenseApportionAmount = 0;
        let amountZeroTip = true;
        let itemNullTip = true;
        let personNullTip = true;
        let expenseApportionProportion = 0;
        expenseApportion.map(apportion => {
          let tempApportion = deepFullCopy(apportion);
          if (tempApportion.amount === 0) {
            amountZeroTip && errorMessages.push(messages('expense-1.key227')/*分摊金额不可为0*/);
            amountZeroTip = false;
          }
          if (!tempApportion.costCenterItems || tempApportion.costCenterItems.length === 0) {
            itemNullTip && errorMessages.push(messages('expense-1.key228')/*费用分摊中的明细信息不完整，请完善*/);
            itemNullTip = false;
          } else {
            let existCostCenterItems = false;
            tempApportion.costCenterItems.map(item => {
              if (item.required && !item.costCenterItemOID) {
                errorMessages.push(`${item.fieldName}:${messages('expense-1.key228')/*费用分摊中的明细信息不完整，请完善*/}`);
                itemNullTip = false;
              }
              if (item.costCenterItemOID) {
                existCostCenterItems = true;
              }
            });
            if (!existCostCenterItems) {
              itemNullTip && errorMessages.push(messages('expense-1.key228')/*费用分摊中的明细信息不完整，请完善*/);
              itemNullTip = false;
            }
          }
          if (!tempApportion.personName) {
            personNullTip && errorMessages.push(messages('expense-1.key229')/*当前费用存在费用分摊信息未填写完整，请先完善分摊信息*/);
            personNullTip = false;
          }
          tempApportion.amount = (tempApportion.amount * 100).toFixed(2) / 100;
          if (-1 < tempApportion.proportion && tempApportion.proportion < 1 && tempApportion.proportion) {
            if (tempApportion.proportion.toString().split('.')[1].length > 4) {
              tempApportion.proportion = parseFloat(tempApportion.proportion.toFixed(4));
            }
          }
          expenseApportionAmount += tempApportion.amount * 100;
          if (tempApportion.proportion) {
            expenseApportionProportion += mulCalculate(tempApportion.proportion, 10000);
          }
          targetApportion.push(tempApportion);
        });
        expenseApportion.some(item => {
          if (item.amount >= 0 !== expenseApportion[0].amount >= 0) {
            errorMessages.push(messages('expense-1.key230')/*分摊金额的符号请保持一致*/);
            return true;
          }
        });
        //判断小数加有精度问题
        if (expenseApportionProportion !== 10000) {
          let precision = queryCurrencyPrecision(nowCurrency.currencyCode);
          let actualAmount = actualApportionAmount || values.amount;
          if (parseFloat((expenseApportionAmount / 100).toFixed(precision)) !== parseFloat(actualAmount.toFixed(precision))) {
            errorMessages.push(messages('expense-1.key231')/*分摊比率和需等于100%*/);
          }
        }
        //分摊行成本中心联动，如果选择了父成本中心，子成本中心不能为空
        let sonCostCenterIsNull = false;
        (targetApportion || []).map(item => {
          !sonCostCenterIsNull && (item.costCenterItems || []).map(costCenterItem => {
            if (costCenterItem.type === 'father' && costCenterItem.costCenterItemOID) { //父成本中心有值
              item.costCenterItems.map(costCenterItem => {
                if (costCenterItem.type === 'son' && !costCenterItem.costCenterItemOID && costCenterItem.required) { //子成本中心没有值
                  errorMessages.push(messages('common.select')/*请选择*/ + costCenterItem.fieldName);
                  sonCostCenterIsNull = true;
                }
              });
            }
          });
        });
      }
    }

    if(expenseType.erAmortiseEnabled && expenseReport) {
      if(expenseAmortise && expenseAmortise.length) {
        if (expenseAmortise.filter(i => Number(i.amount) === 0).length) {
          errorMessages.push(messages('expense-1.key232')/*摊销金额不能为0*/);
        }
        if(expenseAmortise.filter(i => !i.periodId).length) {
          errorMessages.push(messages('expense-1.key233')/*摊销期间不能为空*/);
        }
        if(Number(expenseAmortise.reduce((total, i) => total + Number(i.proportion * 100), 0).toFixed(2)) !== 100) {
          errorMessages.push(messages('expense-1.key234')/*摊销比例和需等于100%*/);
        }
        if(expenseAmortise.filter(i => !!i.periodId).length !== [...new Set(expenseAmortise.filter(i => !!i.periodId).map(i => '' + i.periodId))].length) {
          errorMessages.push(messages('expense-1.key235')/*摊销期间不能重复*/);
        }
      }
    }
    // zt 阶梯模式才有这些处理
    if (
      values.hasOwnProperty('amount') &&
      nowExpense.expenseTypeKey === 'private.car.for.public' &&
      (!unitPriceMode || (unitPriceMode && nowExpense.mileageAllowanceExpenseDTO))
    ) {
      if (pcfpAmountCheck === 2 && values.amount !== nowExpense.orderAmount) {
        errorMessages.push(messages('expense-1.key236')/*费用金额必须等于补贴金额*/);
      }
      if ((pcfpAmountCheck === 1 || !pcfpAmountCheck) && values.amount > nowExpense.orderAmount) {
        errorMessages.push(messages('expense-1.key237')/*费用金额不能大于补贴金额*/);
      }
    }
    if (isRequiredFile(receiptList, expenseType) && attachments.length === 0) {
      errorMessages.push(messages('expense-1.key238')/*请上传附件以便后续审核*/);
    }
    if ((!expenseType.readonly || expenseType.messageKey === "private.car.for.public") && target.data) {
      checkTimeFields(target.data).length && errorMessages.push(...checkTimeFields(target.data));
      checkLocationFields(target.data).length && errorMessages.push(...checkLocationFields(target.data));
    }
    if (errorMessages.length) {
      reject(errorMessages);
    } else {
      resolve();
    }
  })
}

/**
 * 附件是否必填
 * attachmentRequired 用于配置附件是否必填：
 *    0 为不必填
 *    1 为始终必填
 *    2 为有发票时不必填 : 费用中有导入、扫入、录入发票或费用为无票时，附件不必填
 *    3 有发票电子原件不必填
 *    4 仅发票附件均有值时不必填
 * @returns {boolean}
 */
function isRequiredFile(receiptList = [], expenseType) {
  let allHasPdfUrl = true;
  if (receiptList && receiptList.length > 0) {
    receiptList.map(item => {
      !(item.pdfUrl && !item.pdfDamaged) && (allHasPdfUrl = false);
    })
  } else {
    allHasPdfUrl = false;
  }
  return (
    expenseType.attachmentRequired === 1 ||
    (expenseType.attachmentRequired === 2 && expenseType.pasteInvoiceNeeded && receiptList.length === 0) ||
    (expenseType.attachmentRequired === 3 && !allHasPdfUrl) ||
    (expenseType.attachmentRequired === 4 && (!receiptList.length || receiptList.some(item => !item.slicingAttachmentOID)))
  );
}

//检查时间类控件
function checkTimeFields(list) {
  let errorMessages = [];
  let fieldTypeArray = ['DATETIME', 'DATE', 'MONTH'];
  let compareMkArray = [
    {mk1: 'start.time', mk2: 'end.time'},
    {mk1: 'depart.time', mk2: 'arrive.time'},
  ];
  list.map(item => {
    if (~fieldTypeArray.indexOf(item.fieldType)) {
      compareMkArray.map(compareMk => {
        if (item.messageKey === compareMk.mk1) {
          let startTime = item.value;
          let endTime = list.find(element => {
            return element.messageKey === compareMk.mk2 && element.fieldType === item.fieldType && element.sequence > item.sequence;
          });
          if (startTime && endTime && (
              (item.fieldType === 'DATETIME' && moment(startTime).isAfter(endTime.value)) ||
              (item.fieldType === 'DATE' && moment(startTime).isAfter(endTime.value, 'day')) ||
              (item.fieldType === 'MONTH' && moment(startTime).isAfter(endTime.value, 'month'))
            )
          ) {
            errorMessages.push(`${item.name}${messages('expense-1.key239')/*不可晚于*/}${endTime.name}`)
          }
        }
      });
    }
  });
  return errorMessages;
}

//检查地点类控件
function checkLocationFields(list) {
  let errorMessages = [];
  let compareMkArray = [
    {mk1: 'departure.location', mk2: 'destination.location'},
    {mk1: 'departure.city', mk2: 'destination.city'},
  ];
  list.map(item => {
    compareMkArray.map(compareMk => {
      if (item.messageKey === compareMk.mk1) {
        let endLocationItem = list.find(element => {
          return element.messageKey === compareMk.mk2 && element.fieldType === item.fieldType && element.sequence > item.sequence;
        }) || {};
        let startLocation = item.value;
        let endLocation = endLocationItem.value;
        if (item.fieldType === 'GPS' && item.value) {
          startLocation = JSON.parse(item.value).address;
        }
        if (endLocationItem.fieldType ===  'GPS' && endLocationItem.value) {
          endLocation = JSON.parse(endLocationItem.value).address;
        }
        if (startLocation && startLocation === endLocation) {
          errorMessages.push(messages('expense-1.key240',{arg1: item.name,arg2: endLocationItem.name})/*{arg1}与{arg2}不可一致*/)
        }
      }
    });
  });
  return errorMessages;
}

//检查城市控件，弱管控 messageKey：location
function checkLocation(list, expenseType) {
  return new Promise(resolve => {
    let values = [];
    list && list.map(item => {
      if (item.fieldType === 'LOCATION' && item.messageKey === 'location') {
        values.push({ name: item.name, value: item.value });
      }
    });
    if (
      (!expenseType.readonly || expenseType.messageKey === "private.car.for.public") &&
      values[0] && values[1] && values[0].value && values[0].value === values[1].value
    ) {
      Modal.confirm({
        title: messages('common.info')/*提示*/,
        content: messages('expense-1.key241',{arg1: values[0].name,arg2: values[1].name})/*{arg1}与{arg2}值相同，请确认是否保存费用*/,
        okText: messages('common.save')/*保存*/,
        cancelText: messages('common.back')/*返回*/,
        onOk: () => resolve()
      })
    } else {
      resolve();
    }
  })
}

//发票字段是否不可编辑
function isFieldDisabled(receipt, itemName, pageFrom) {
  //支付宝、微信来源发票
  const types = ['ALICARDSIGN', 'APPCARDSIGN', 'JSCARDSIGN', 'WXFWCARDSIGN'];
  //区块链发票的校验码有值时不可编辑
  if (receipt.blockchain && itemName === 'checkCode') {
    return !!receipt.checkCode;
  }
  //扫一扫
  if (receipt.cardsignType === 'SCANNING') {
    // 增值税卷式发票
    if (['11'].includes(receipt.invoiceTypeNo)) {
      return ['invoiceTypeNo', 'invoiceCode', 'invoiceNumber'].includes(itemName);
    }
    // 增值税发票、机动车销售发票
    else if (['01', '03'].includes(receipt.invoiceTypeNo)) {
      return ['invoiceTypeNo', 'invoiceCode', 'invoiceNumber', 'invoiceDate'].includes(itemName);
    }
    // 横版增值税发票
    else if (['04', '10', '14', '20'].includes(receipt.invoiceTypeNo)) {
      return ['invoiceTypeNo', 'invoiceCode', 'invoiceNumber', 'invoiceDate', 'checkCode'].includes(itemName)
    }
  } else {
    return pageFrom !== 'auditCheck' && types.includes(receipt.cardsignType)
  }
}

//差补费用提示信息
function getSubsidyTips(data) {
  let isAllowance = data && data.filter(item => item.fieldType === 'ALLOWANCE_DEDUCTION' && item.showOnList).length > 0;
  return isAllowance ? "<div>" +
    messages('expense-1.key242')/*差补费用修改说明：*/ +
    messages('expense-1.key243')/*您好，目前不支持编辑差补明细修改补贴费用，如需修改，请点击补贴明细中【修改补贴】*/ +
    "<br/>" +
    messages('expense-1.key244')/*扣减规则修改说明：*/ +
    messages('expense-1.key243')/*您好，目前不支持编辑差补明细修改补贴费用，如需修改，请点击补贴明细中【修改补贴】*/ +
    "</div>" : "<div>" +
    messages('expense-1.key242')/*差补费用修改说明：*/ +
    messages('expense-1.key243')/*您好，目前不支持编辑差补明细修改补贴费用，如需修改，请点击补贴明细中【修改补贴】*/ +
    "</div>"
}

function invoiceAttachmentInfo(configValue, type) {
  switch (type) {
    case 'extra':
      let supportType = configValue === '40' ? 'PDF/OFD' : 'PNG/JPG/JPEG/PDF/OFD';
      return `${messages('expense-1.key245')/*支持格式*/}: ${supportType}`;
    case 'fileType':
      return configValue === '40' ? ['pdf', 'ofd'] : ['jpg', 'png', 'jpeg', 'pdf', 'ofd'];
    case 'accept':
      return configValue === '40' ? 'application/pdf,.ofd' : 'image/*,application/pdf,.ofd';
  }
}

// 发票信息是否完整（不需要补录）
function isCompleteInvoice(resultCode) {
  // 不完整的code
  // R_2002：补录税率
  // R_2007：补录价税合计
  // R_2008：补录税率／价税合计
  // R_2009：信息不全
  // R_2012：限制附件为pdf原件
  // R_2013：pdf原件信息匹配失败
  const resultCodes = ['R_2002', 'R_2007', 'R_2008', 'R_2009', 'R_2012', 'R_2013'];
  return !resultCodes.includes(resultCode);
}

function setFormValue(form, values) {
  const { getFieldsValue, setFieldsValue } = form;
  Object.keys(values || {}).map(key => {
    getFieldsValue().hasOwnProperty(key) && setFieldsValue({
      [key]: values[key]
    })
  })
}

export default {
  validateFieldsValue,
  isRequiredFile,
  checkLocation,
  isFieldDisabled,
  getSubsidyTips,
  invoiceAttachmentInfo,
  isCompleteInvoice,
  setFormValue
}
